package com.my.lucky.util;

import com.my.lucky.model.Stock;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 移动平均线计算工具类
 */
public class MovingAverageCalculator {

    /**
     * 计算简单移动平均线 (SMA)
     *
     * @param stocks 股票数据列表，按日期升序排序
     * @param period 周期（如5日、10日、20日等）
     * @return 移动平均线数据，长度等于原数据长度，不足周期的位置补null
     */
    public static List<Double> calculateSMA(List<Stock> stocks, int period) {
        if (stocks == null || stocks.isEmpty() || period <= 0) {
            return Collections.emptyList();
        }

        List<Double> smaList = new ArrayList<>(stocks.size());

        // 前period-1个位置补null
        for (int i = 0; i < period - 1; i++) {
            smaList.add(null);
        }

        // 计算移动平均线
        for (int i = period - 1; i < stocks.size(); i++) {
            double sum = 0;
            for (int j = 0; j < period; j++) {
                sum += stocks.get(i - j).getClose();
            }
            smaList.add(sum / period);
        }

        return smaList;
    }

    /**
     * 计算指数移动平均线 (EMA)
     *
     * @param stocks 股票数据列表，按日期升序排序
     * @param period 周期（如5日、10日、20日等）
     * @return 移动平均线数据，长度等于原数据长度，不足周期的位置补null
     */
    public static List<Double> calculateEMA(List<Stock> stocks, int period) {
        if (stocks == null || stocks.isEmpty() || period <= 0) {
            return Collections.emptyList();
        }

        List<Double> emaList = new ArrayList<>(stocks.size());
        double multiplier = 2.0 / (period + 1);

        // 第一个EMA值使用前period天的简单平均值
        double sum = 0;
        for (int i = 0; i < period; i++) {
            sum += stocks.get(i).getClose();
        }
        double prevEma = sum / period;

        // 前period-1个位置补null
        for (int i = 0; i < period - 1; i++) {
            emaList.add(null);
        }
        emaList.add(prevEma);

        // 计算其余的EMA值
        for (int i = period; i < stocks.size(); i++) {
            double close = stocks.get(i).getClose();
            double ema = (close - prevEma) * multiplier + prevEma;
            emaList.add(ema);
            prevEma = ema;
        }

        return emaList;
    }

    /**
     * 计算加权移动平均线 (WMA)
     *
     * @param stocks 股票数据列表，按日期升序排序
     * @param period 周期（如5日、10日、20日等）
     * @return 移动平均线数据，长度等于原数据长度，不足周期的位置补null
     */
    public static List<Double> calculateWMA(List<Stock> stocks, int period) {
        if (stocks == null || stocks.isEmpty() || period <= 0) {
            return Collections.emptyList();
        }

        List<Double> wmaList = new ArrayList<>(stocks.size());

        // 计算权重之和 1+2+3+...+period
        int weightSum = (period * (period + 1)) / 2;

        // 前period-1个位置补null
        for (int i = 0; i < period - 1; i++) {
            wmaList.add(null);
        }

        // 计算WMA
        for (int i = period - 1; i < stocks.size(); i++) {
            double sum = 0;
            for (int j = 0; j < period; j++) {
                // 距离当前日期越近，权重越大
                sum += stocks.get(i - j).getClose() * (period - j);
            }
            wmaList.add(sum / weightSum);
        }

        return wmaList;
    }

    /**
     * 判断是否形成黄金交叉（快线上穿慢线）
     *
     * @param fastMA 快线数据
     * @param slowMA 慢线数据
     * @param index  当前位置
     * @return 是否形成黄金交叉
     */
    public static boolean isGoldenCross(List<Double> fastMA, List<Double> slowMA, int index) {
        if (index <= 0 || index >= fastMA.size() || index >= slowMA.size()) {
            return false;
        }

        Double prevFast = fastMA.get(index - 1);
        Double prevSlow = slowMA.get(index - 1);
        Double currFast = fastMA.get(index);
        Double currSlow = slowMA.get(index);

        return prevFast != null && prevSlow != null && currFast != null && currSlow != null
                && prevFast <= prevSlow && currFast > currSlow;
    }

    /**
     * 判断是否形成死亡交叉（快线下穿慢线）
     *
     * @param fastMA 快线数据
     * @param slowMA 慢线数据
     * @param index  当前位置
     * @return 是否形成死亡交叉
     */
    public static boolean isDeathCross(List<Double> fastMA, List<Double> slowMA, int index) {
        if (index <= 0 || index >= fastMA.size() || index >= slowMA.size()) {
            return false;
        }

        Double prevFast = fastMA.get(index - 1);
        Double prevSlow = slowMA.get(index - 1);
        Double currFast = fastMA.get(index);
        Double currSlow = slowMA.get(index);

        return prevFast != null && prevSlow != null && currFast != null && currSlow != null
                && prevFast >= prevSlow && currFast < currSlow;
    }
}